package com.yida.wy.vote.outside.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.json.JSONUtil;
import com.yida.common.core.constant.Constants;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.DateUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.common.security.utils.SecurityUtils;
import com.yida.gwj.api.domain.dto.GwjGVoteProjectStatisticsDataDTO;
import com.yida.wy.common.constant.WyConstants;
import com.yida.wy.common.domain.WyBaseCommunity;
import com.yida.wy.common.domain.request.WyOwnerLoginRequest;
import com.yida.wy.common.enums.WyBusinessHouseStatus;
import com.yida.wy.common.utils.CheckDiffList;
import com.yida.wy.vote.outside.domain.WyVoteProject;
import com.yida.wy.vote.outside.domain.WyVoteResult;
import com.yida.wy.vote.outside.domain.WyVoteResultDetail;
import com.yida.wy.vote.outside.domain.WyVoteTemplate;
import com.yida.wy.vote.outside.domain.dto.*;
import com.yida.wy.vote.outside.domain.request.WyVoteOwnerProjectQueryRequest;
import com.yida.wy.vote.outside.domain.request.WyVoteResultRequest;
import com.yida.wy.vote.outside.enums.WyVoteInitiateTypeEnum;
import com.yida.wy.vote.outside.enums.WyVoteStatusEnum;
import com.yida.wy.vote.outside.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 业主投票端Service业务层处理
 *
 * @author lqq
 * @date 2023-03-17
 */
@Service
public class WyVoteOwnerServiceImpl implements IWyVoteOwnerService {

    @Resource
    private IWyVoteResultService voteResultService;

    @Resource
    private IWyVoteProjectService voteProjectService;

    @Resource
    private IWyVoteTemplateService voteTemplateService;

    @Resource
    private IWyVoteStatisticsService voteStatisticsService;

    @Resource
    private IWyVoteOwnerLoginInfoService loginInfoService;

    @Resource
    private IWyVoteResultDetailService voteResultDetailService;

    @Resource
    private IWyBaseDataService gwjBaseDataService;

    @Override
    public List<WyVoteResultDTO> checkOwnerInfo(WyOwnerLoginRequest request) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(request.getOwnerPhone(), request.getOwnerName())) {
            loginInfoService.recordVoteOwnerLoginInfo(request.getOwnerName(), Constants.LOGIN_FAIL, "姓名/手机号码必须填写");
            throw new ServiceException("操作失败,姓名/手机号码必须填写");
        }
        //校验手机格式
        if (!PhoneUtil.isPhone(request.getOwnerPhone())) {
            loginInfoService.recordVoteOwnerLoginInfo(request.getOwnerName(), Constants.LOGIN_FAIL, "手机号码格式有误");
            throw new ServiceException("操作失败,手机号码格式有误");
        }
//        //校验身份证格式
//        if (!IdcardUtil.isValidCard(request.getCardNum())) {
//            loginInfoService.recordVoteOwnerLoginInfo(request.getOwnerName(), Constants.LOGIN_FAIL, "身份证号码格式有误");
//            throw new ServiceException("操作失败,身份证号码格式有误");
//        }
        //查询用户集合
        List<WyVoteResultDTO> owners = voteResultService.selectVoteResultList(new WyVoteResultDTO() {{
            setOwnerPhone(request.getOwnerPhone());
            setOwnerName(request.getOwnerName());
//            setCardNum(request.getCardNum());
            setSelectFlag(WyBusinessHouseStatus.CONFIRM.getCode());
        }});
        if (StringUtils.isEmpty(owners)) {
            loginInfoService.recordVoteOwnerLoginInfo(request.getOwnerName(), Constants.LOGIN_FAIL, "查无用户信息");
            throw new ServiceException("操作失败,查无用户信息");
        }
        return owners;
    }

    @Override
    public List<Long> getOwnerResultIds(List<WyVoteResultDTO> results, String loginPhone) {
        //根据小区ID把业主分种并且 同一小区多套房的业主只取其一
        Map<Long, List<WyVoteResultDTO>> map = results.stream().collect(Collectors.groupingBy(WyVoteResultDTO::getVoteId));
        List<Long> resultIds = new ArrayList<>();
        map.forEach((key, value) -> {
            resultIds.add(value.get(0).getResultId());
        });
        return resultIds;
    }

    /**
     * 用户投票
     *
     * @param request 投票结果
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrUpdateVoteResult(WyVoteResultRequest request) {
        WyVoteProject voteProject = voteProjectService.selectVoteProjectByVoteId(request.getVoteId());
        if (StringUtils.isNull(voteProject)) {
            throw new ServiceException("投票失败,查无投票信息");
        }
        if (!voteProject.getVoteStatus().equals(WyVoteStatusEnum.VOTE_ING.getCode())) {
            throw new ServiceException("投票失败,投票不在进行中");
        }
        if (DateUtil.compare(DateUtils.getNowDate(), voteProject.getEndTime()) > 0) {
            throw new ServiceException("投票失败,投票已结束");
        }
        if (voteProject.getInitiateType().equals(WyVoteInitiateTypeEnum.E_VOTE.getCode())) {
            long selectItemCount = request.getVoteItems().stream().filter(i -> "1".equals(i.getSelectFlag())).count();
            if (voteProject.getMaxSelectItem() < selectItemCount) {
                throw new ServiceException("投票失败,最大只能选择" + voteProject.getMaxSelectItem() + "项");
            }
            if (voteProject.getMinSelectItem() > selectItemCount) {
                throw new ServiceException("投票失败,最少需选择" + voteProject.getMinSelectItem() + "项");
            }
        }
        //查询业主在当前投票中的所有票设置一样的投票结果
        WyVoteResultDTO resultDTO = voteResultService.selectVoteResultByResultId(request.getResultId());
        List<WyVoteResultDTO> resultsByPhone = voteResultService.selectVoteResultList(new WyVoteResultDTO(){{
            setOwnerPhone(resultDTO.getOwnerPhone());
            setVoteId(request.getVoteId());
        }});
//        List<WyVoteResultDTO> resultsByCard = voteResultService.selectVoteResultList(new WyVoteResultDTO(){{
//            setCardNum(resultDTO.getCardNum());
//            setVoteId(request.getVoteId());
//        }});
//        resultsByPhone.addAll(resultsByCard);
        List<WyVoteResultDTO> results = resultsByPhone.stream().filter(CheckDiffList.distinctByKey(WyVoteResultDTO::getResultId)).collect(Collectors.toList());
        //保存投票结果
        results.forEach(r ->  {
            WyVoteResult result = BeanUtil.copyProperties(request, WyVoteResult.class);
            result.setResultId(r.getResultId());
            result.setVoteTime(DateUtils.getNowDate());
            result.setResultJson(JSONUtil.toJsonStr(JSONUtil.parseArray(request.getVoteItems(), false)));
            if (1 != voteResultService.updateVoteResult(result)) {
                throw new ServiceException("投票失败,保存投票结果失败");
            }
            //删除之前的投票结果详情
            if (StringUtils.isNotEmpty(voteResultDetailService.selectVoteResultDetailList(new WyVoteResultDetail() {{
                setResultId(result.getResultId());
            }}))) {
                if (voteResultDetailService.deleteVoteResultDetailByResultId(result.getResultId()) <= 0) {
                    throw new ServiceException("投票失败,重置投票结果详情失败");
                }
            }
            //保存投票详情
            List<WyVoteResultDetail> details = BeanUtil.copyToList(request.getResultDetails(), WyVoteResultDetail.class);
            details.forEach(d -> {
                d.setResultId(result.getResultId());
                d.setVoteId(result.getVoteId());
                d.setCreateBy(StringUtils.isNull(SecurityUtils.getLoginUser()) ? "" : SecurityUtils.getLoginUser().getSysOutsideUser().getRealName());
                d.setCreateTime(DateUtils.getNowDate());
            });
            if (0 == voteResultDetailService.insertBatchVoteResultDetail(details)) {
                throw new ServiceException("投票失败,保存投票结果详情失败");
            }
        });
        return Boolean.TRUE;
    }

    /**
     * 查询业主可投票项目列表
     *
     * @param request 业主ID
     * @return 投票项目集合
     */
    @Override
    public List<WyVoteOwnerProjectListDTO> selectVoteOwnerProjectList(WyVoteOwnerProjectQueryRequest request) {
        List<WyVoteOwnerProjectListDTO> list = voteProjectService.selectVoteOwnerProjectList(request);
        list.forEach(p -> {
            if (DateUtil.compare(DateUtils.getNowDate(), p.getEndTime()) > 0) {
                p.setVoteStatus(WyVoteStatusEnum.VOTE_END.getCode());
            }
        });
        return list;
    }

    /**
     * 投票详情
     *
     * @param voteId   投票ID
     * @param resultId 用户投票结果ID
     * @return 结果
     */
    @Override
    public WyVoteOwnerProjectDetailDTO voteDetail(Long voteId, Long resultId) {
        //查询投票
        WyVoteProject project = voteProjectService.selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        //查询模板
        WyVoteTemplate template = voteTemplateService.selectVoteTemplateByVoteId(voteId);
        if (StringUtils.isNull(template)) {
            throw new ServiceException("查无投票选项");
        }
        //查询用户投票结果json
        WyVoteResultDTO result = voteResultService.selectVoteResultByResultId(resultId);
        //返回
        WyVoteOwnerProjectDetailDTO dto = BeanUtil.copyProperties(project, WyVoteOwnerProjectDetailDTO.class);
        if (dto.getVoteStatus().equals(WyVoteStatusEnum.VOTE_ING.getCode()) && DateUtil.compare(DateUtils.getNowDate(), dto.getEndTime()) > 0) {
            dto.setVoteStatus(WyVoteStatusEnum.VOTE_END.getCode());
        }
        dto.setTemplateJson(StringUtils.isBlank(result.getResultJson()) ? template.getTemplateJson() : result.getResultJson());
        //记录次数
        if (StringUtils.equals(WyConstants.NO, result.getBrowseFlag())) {
            project.setAccessNum(project.getAccessNum() + 1);
            if (1 != voteProjectService.updateVoteProjectAccessNum(project)) {
                throw new ServiceException("更新访问次数失败");
            }
            if (1 != voteResultService.updateVoteResult(new WyVoteResult() {{
                setResultId(resultId);
                setBrowseFlag(WyConstants.YES);
            }})) {
                throw new ServiceException("更新访问次数失败");
            }
        }
        return dto;
    }


    /**
     * 投票详情
     *
     * @param voteId   投票ID
     * @param resultId 用户投票结果ID
     * @return 结果
     */
    @Override
    public WyVoteOwnerGwjProjectDetailDTO voteGwjDetail(Long voteId, Long resultId) {
        //查询投票
        WyVoteProject project = voteProjectService.selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        //查询模板
        WyVoteTemplate template = voteTemplateService.selectVoteTemplateByVoteId(voteId);
        if (StringUtils.isNull(template)) {
            throw new ServiceException("查无投票选项");
        }
        //查询用户投票结果json
        WyVoteResultDTO result = voteResultService.selectVoteResultByResultId(resultId);
        //投票信息
        WyVoteOwnerGwjProjectDetailDTO dto = BeanUtil.copyProperties(project, WyVoteOwnerGwjProjectDetailDTO.class);
        if (dto.getVoteStatus().equals(WyVoteStatusEnum.VOTE_ING.getCode()) && DateUtil.compare(DateUtils.getNowDate(), dto.getEndTime()) > 0) {
            dto.setVoteStatus(WyVoteStatusEnum.VOTE_END.getCode());
        }
        //用户投票记录
        dto.setTemplateJson(StringUtils.isBlank(result.getResultJson()) ? template.getTemplateJson() : result.getResultJson());
        //投票细节
        GwjGVoteProjectStatisticsDataDTO gwjGVoteProjectStatisticsDataDTO = voteStatisticsService.gVoteProjectStatistics(voteId);
        dto.setTotalOwner(gwjGVoteProjectStatisticsDataDTO.getTotalOwner());
        dto.setTotalSize(gwjGVoteProjectStatisticsDataDTO.getTotalSize());
        dto.setItemCount(voteStatisticsService.voteResultDetailStatistics(voteId));
        //记录次数
        if (StringUtils.equals(WyConstants.NO, result.getBrowseFlag())) {
            project.setAccessNum(project.getAccessNum() + 1);
            dto.setAccessNum(dto.getAccessNum() + 1);
            if (1 != voteProjectService.updateVoteProjectAccessNum(project)) {
                throw new ServiceException("更新访问次数失败");
            }
            if (1 != voteResultService.updateVoteResult(new WyVoteResult() {{
                setResultId(resultId);
                setBrowseFlag(WyConstants.YES);
            }})) {
                throw new ServiceException("更新访问次数失败");
            }
        }
        return dto;
    }

    /**
     * 业主票根
     *
     * @param voteId   投票ID
     * @param resultId 用户投票结果ID
     * @return 结果
     */
    @Override
    public WyVoteOwnerTicketStubDetailDTO ticketStub(Long voteId, Long resultId) {
        //查询投票
        WyVoteProject project = voteProjectService.selectVoteProjectByVoteId(voteId);
        if (StringUtils.isNull(project)) {
            throw new ServiceException("查无投票信息");
        }
        //查询用户信息
        WyVoteResultDTO result = voteResultService.selectVoteResultByResultId(resultId);
        //查询用户在小区的所有房屋信息
        List<WyVoteResultDTO> allResults = voteResultService.selectVoteResultList(new WyVoteResultDTO() {{
            setCommunityId(project.getCommunityId());
            setOwnerPhone(result.getOwnerPhone());
        }});
        //查询小区
        WyBaseCommunity community = gwjBaseDataService.selectGwjBaseCommunityByGwjBaseCommunityId(project.getCommunityId());
//        R<SysArea> sysAreaR = remoteAreaService.getVoteAreaInfo(project.getAreaId());
//        R<SysArea> sysStreetR = remoteAreaService.getVoteAreaInfo(project.getStreetId());
        return new WyVoteOwnerTicketStubDetailDTO() {{
            setCommunityName(StringUtils.isNull(community) ? "" : community.getCommunityName());
//            setAreaName(CheckRemoteServiceResultUtils.isDataNull(sysAreaR) ? "" : sysAreaR.getData().getAreaName());
//            setStreetName(CheckRemoteServiceResultUtils.isDataNull(sysStreetR) ? "" : sysStreetR.getData().getAreaName());
            setOwnerName(result.getOwnerName());
            setOwnerPhone(result.getOwnerPhone());
            setHouseLocation(allResults.stream().map(WyVoteResultDTO::getHouseLocation).collect(Collectors.joining(",")));
            setTotalSize(houseSizeStatistics(allResults));
            setResultJson(result.getResultJson());
        }};
    }

    /**
     * 计算房屋面积，现房面积优先
     *
     * @param houses 房屋集合
     * @return /
     */
    private BigDecimal houseSizeStatistics(List<WyVoteResultDTO> houses) {
        if (StringUtils.isEmpty(houses)) {
            return BigDecimal.ZERO;
        }
        return houses.stream().map(h -> {
            if (StringUtils.isNotNull(h.getActualSize()) && h.getActualSize().compareTo(BigDecimal.ZERO) != 0) {
                return h.getActualSize();
            } else {
                return StringUtils.isNotNull(h.getForecastSize()) ? h.getForecastSize() : BigDecimal.ZERO;
            }
        }).reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}
